package com.example.takeaway.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.takeaway.common.ResponseEnum;
import com.example.takeaway.constant.OrderStatusEnum;
import com.example.takeaway.constant.PayStatusEnum;
import com.example.takeaway.converter.OrderConverter;
import com.example.takeaway.exception.BusException;
import com.example.takeaway.mapper.*;
import com.example.takeaway.model.PageVO;
import com.example.takeaway.model.bo.*;
import com.example.takeaway.model.dto.OrderSubmitDTO;
import com.example.takeaway.model.dto.ShopOrderPageQuery;
import com.example.takeaway.model.vo.*;
import com.example.takeaway.service.CartItemService;
import com.example.takeaway.service.OrderService;
import com.example.takeaway.websocket.ShopOrderListener;
import com.example.takeaway.websocket.message.OrderNewMessage;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author 邢晨旭
 * @since 2023-10-12
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    CartItemService cartItemService;
    @Resource
    ShopMapper shopMapper;

    @Resource
    DeliveryAddressMapper deliveryAddressMapper;

    @Resource
    OrderAddressMapper orderAddressMapper;

    @Resource
    OrderItemMapper orderItemMapper;

    @Resource
    StringRedisTemplate stringRedisTemplate;


    @Resource
    OrderConverter converter;

    @Override
    public OrderReviewVO review(Long shopId, Long userId) {
        CartVO cartVO = cartItemService.queryCartList(shopId, userId);
        List<CartItemVO> cartItems = cartVO.getCartItems();
        if (cartItems.size() == 0) {
            //购物车为空
            throw new BusException(ResponseEnum.CART_EMPTY);
        }
        OrderReviewVO orderReviewVO = new OrderReviewVO();
        orderReviewVO.setTotalPrice(cartVO.getTotalPrice());
        orderReviewVO.setPackagingPrice(cartVO.getPackagingPrice());
        orderReviewVO.setCartItems(converter.toOrderReview(cartItems));
        //查询店铺信息
        Shop shop = shopMapper.selectById(shopId);
        orderReviewVO.setShopId(shopId);
        orderReviewVO.setShopName(shop.getShopName());
        //查询默认地址
        AddressVO address = deliveryAddressMapper.queryDefaultAddress(userId);
        orderReviewVO.setDefaultAddress(address);
        String token = IdUtil.fastSimpleUUID();
        stringRedisTemplate.opsForValue().set("order:submit:check:repeat:" + token, "1", 60 * 5, TimeUnit.MINUTES);
        orderReviewVO.setToken(token);
        return orderReviewVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long submit(OrderSubmitDTO orderSubmit) {
        if (!Boolean.TRUE.equals(stringRedisTemplate.hasKey("order:submit:check:repeat:" + orderSubmit.getToken()))) {
            throw new BusException(ResponseEnum.ORDER_SUBMIT_ERROR);
        }
        //todo 从token中获取用户id
        Long userId = 111L;
        //查询购物车数据
        CartVO cartVO = cartItemService.queryCartList(orderSubmit.getShopId(), userId);
        List<CartItemVO> cartItems = cartVO.getCartItems();
        if (cartItems.size() == 0) {
            //购物车为空
            throw new BusException(ResponseEnum.CART_EMPTY);
        }
        //创建订单
        Order order = converter.toOrder(orderSubmit);
        order.setUserId(userId);
        //todo 生成订单编号
        long orderNumber = IdUtil.getSnowflakeNextId();
        order.setOrderNumber(orderNumber);
        //todo 默认支付成功
        order.setStatus(OrderStatusEnum.WAITING.getCode());
        order.setOrderTime(LocalDateTime.now());
        order.setPaymentStatus(PayStatusEnum.PAID.getCode());
        order.setTotalAmount(cartVO.getTotalPrice());
        order.setPackagingFee(cartVO.getPackagingPrice());
        baseMapper.insert(order);
        //保存地址信息
        DeliveryAddress address = deliveryAddressMapper.selectById(orderSubmit.getAddressId());
        if (address == null || address.getIsDeleted() == 1) {
            throw new BusException(ResponseEnum.ADDRESS_NOT_EXIST);
        }
        OrderAddress orderAddress = new OrderAddress();
        orderAddress.setOrderId(order.getId());
        orderAddress.setRecipientName(address.getRecipientName());
        orderAddress.setRecipientPhone(address.getPhoneNumber());
        orderAddress.setDeliveryAddress(address.getDetailedAddress());
        orderAddressMapper.insert(orderAddress);
        List<OrderItem> orderItems = converter.toOrderItem(cartItems);
        orderItems.forEach(orderItem -> orderItem.setOrderId(order.getId()));
        //保存订单项
        orderItemMapper.insertBatch(orderItems);
        //清空购物车
        cartItemService.delCart(orderSubmit.getShopId(), userId);
        //发送消息
        ShopOrderListener.send(orderSubmit.getShopId().toString(), new OrderNewMessage(order.getId().toString()));
        return orderNumber;
    }

    @Override
    public List<OrderListVO> userOrderList(Long userId, Integer status) {
        return baseMapper.queryOrderListByUserId(userId, status);
    }

    @Override
    public PageVO<OrderVO> shopOrderList(ShopOrderPageQuery pageQuery) {
        Integer status = pageQuery.getStatus();
        Page<OrderVO> page = PageDTO.of(pageQuery.getPage(), pageQuery.getSize());
        List<OrderVO> list = baseMapper.queryShopOder(page, pageQuery);
        if (list != null && list.size() > 0) {
            List<Long> orderIds = list.stream().map(OrderVO::getId).collect(Collectors.toList());
            if (status == 1 || status == 2 || status == 3) {
                //查询菜品信息
                List<OrderItemVO> orderItems = baseMapper.queryItemByOrderIds(orderIds);
                Map<Long, List<OrderItemVO>> map = orderItems.stream().collect(Collectors.groupingBy(OrderItemVO::getOrderId));
                list.forEach(item -> {
                    item.setOrderItems(map.get(item.getId()));
                });
            }
        }
        PageVO<OrderVO> pageVO = new PageVO<>();
        pageVO.setTotal(page.getTotal());
        pageVO.setPage(pageQuery.getPage());
        pageVO.setSize(pageQuery.getSize());
        pageVO.setList(list);
        return pageVO;
    }

    @Override
    public void changeOrderStatus(Long orderId, Integer code) {
        Order order = baseMapper.selectById(orderId);
        if (order == null || order.getIsDeleted() == 1) {
            throw new BusException(ResponseEnum.ORDER_NOT_EXIST);
        }
        //2:备餐中, 3:配送中,4:已完成,
        //code 1 status 0
        //code 2 status 1
        //code 3 status 2
        //code 4 status 3
        if (code - 1 == order.getStatus()) {
            //可以修改
            order.setStatus(code);
            order.setUpdateTime(new Date());
            baseMapper.changeStatus(orderId, code);
            return;
        }
        switch (code) {
            case 2:
                throw new BusException("该订单已被接单");
            case 3:
                throw new BusException("该订单不是备餐状态,无法配送");
            case 4:
                throw new BusException("订单未派送,无法完成");
            default:
                throw new BusException("订单状态异常");
        }
    }

    @Override
    public OrderVO orderDetail(Long orderId) {
        return baseMapper.queryDetailById(orderId);
    }

    @Override
    public void cancelOrder(Long orderId, String reason) {
        Order order = baseMapper.selectById(orderId);
        if (order == null || order.getIsDeleted() == 1) {
            throw new BusException(ResponseEnum.ORDER_NOT_EXIST);
        }
        if (PayStatusEnum.PAID.getCode().equals(order.getPaymentStatus())) {
            //todo 退款操作
            order.setPaymentStatus(PayStatusEnum.REFUNDED.getCode());
        }
        order.setStatus(OrderStatusEnum.CANCELED.getCode());
        order.setCancelReason(reason);
        order.setCancelTime(LocalDateTime.now());
        order.setUpdateTime(new Date());
        baseMapper.updateById(order);
    }
}
